"""
隐患追踪管理视图模块

此模块包含隐患追踪管理系统的所有视图函数，提供完整的REST API接口。
包括隐患任务的创建、读取、更新、删除等核心功能。

主要功能：
- 隐患任务CRUD操作
- 从安全评价报告自动创建隐患任务
- 隐患状态管理和跟踪
- 附件文件上传和管理
- 统计数据和报表功能

作者：矿山安全评价系统开发团队
版本：1.0.0
更新时间：2025-10-12
"""

import json
import logging
import os
from datetime import datetime, timedelta
from typing import Dict, Any, Optional

from django.shortcuts import get_object_or_404
from django.http import JsonResponse, HttpResponse, HttpRequest
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.utils import timezone
from django.core.paginator import Paginator
from django.db.models import Q, Count
from django.core.exceptions import ValidationError
from django.db import transaction
from django.conf import settings

from .models import HazardTracking
from evaluationmine.models import SafetyEvaluation

# 配置日志记录器
logger = logging.getLogger(__name__)

# ========== 常量定义 ==========
MAX_PAGE_SIZE = 100
DEFAULT_PAGE_SIZE = 10
VALID_STATUS_CHOICES = ['待整改', '整改中', '整改完成', '复核通过']
VALID_LEVEL_CHOICES = ['C级(一般)', 'D级(较差)']

# ========== 辅助函数 ==========

def create_error_response(message: str, status_code: int = 400, error_code: Optional[str] = None) -> JsonResponse:
    """创建标准化的错误响应"""
    response_data = {
        'success': False,
        'error': message,
        'timestamp': timezone.now().isoformat()
    }
    if error_code:
        response_data['error_code'] = error_code
    
    logger.warning(f"API错误: {message} (状态码: {status_code})")
    return JsonResponse(response_data, status=status_code)


def create_success_response(data: Any = None, message: str = None) -> JsonResponse:
    """创建标准化的成功响应"""
    response_data = {
        'success': True,
        'timestamp': timezone.now().isoformat()
    }
    if data is not None:
        response_data['data'] = data
    if message:
        response_data['message'] = message
    
    return JsonResponse(response_data)


def validate_pagination_params(request: HttpRequest) -> tuple:
    """验证分页参数"""
    try:
        page = max(1, int(request.GET.get('page', 1)))
        page_size = min(MAX_PAGE_SIZE, max(1, int(request.GET.get('page_size', DEFAULT_PAGE_SIZE))))
        return page, page_size
    except (ValueError, TypeError):
        return 1, DEFAULT_PAGE_SIZE


# ========== 核心视图函数 ==========

@csrf_exempt
@require_http_methods(["GET", "POST"])
def hazard_tracking_list(request: HttpRequest) -> JsonResponse:
    """
    隐患追踪列表API
    
    GET请求：获取隐患追踪列表，支持分页和多条件筛选
    POST请求：创建新的隐患追踪任务
    
    查询参数（GET）：
        - page: 页码（默认1）
        - page_size: 每页大小（默认10，最大100）
        - keyword: 关键词搜索（任务编号或矿山名称）
        - status: 整改状态筛选
        - safety_level: 安全等级筛选
        - mine_name: 矿山名称筛选
    
    Returns:
        JsonResponse: 包含隐患追踪列表和分页信息的JSON响应
    """
    if request.method == 'GET':
        try:
            # 验证分页参数
            page, page_size = validate_pagination_params(request)
            
            # 获取筛选参数
            keyword = request.GET.get('keyword', '').strip()
            status = request.GET.get('status', '').strip()
            safety_level = request.GET.get('safety_level', '').strip()
            mine_name = request.GET.get('mine_name', '').strip()
            
            # 构建查询集
            queryset = HazardTracking.objects.all().order_by('-assigned_date')
            
            # 应用筛选条件
            if keyword:
                queryset = queryset.filter(
                    Q(task_id__icontains=keyword) |
                    Q(mine_name__icontains=keyword) |
                    Q(indicator_name__icontains=keyword)
                )
            
            if status and status in VALID_STATUS_CHOICES:
                queryset = queryset.filter(status=status)
                
            if safety_level and safety_level in VALID_LEVEL_CHOICES:
                queryset = queryset.filter(safety_level=safety_level)
                
            if mine_name:
                queryset = queryset.filter(mine_name__icontains=mine_name)
            
            # 分页处理
            paginator = Paginator(queryset, page_size)
            
            if page > paginator.num_pages and paginator.num_pages > 0:
                return create_error_response('请求的页码超出范围', 404, 'PAGE_OUT_OF_RANGE')
            
            page_obj = paginator.get_page(page)
            
            # 构建响应数据
            hazards = []
            for hazard in page_obj:
                try:
                    hazard_data = {
                        'task_id': hazard.task_id,
                        'mine_name': hazard.mine_name,
                        'indicator_name': hazard.indicator_name,
                        'safety_level': hazard.safety_level,
                        'trigger_condition': hazard.trigger_condition,
                        'remediation_suggestion': hazard.remediation_suggestion,
                        'responsible_person': hazard.responsible_person,
                        'status': hazard.status,
                        'assigned_date': hazard.assigned_date.strftime('%Y-%m-%d %H:%M:%S'),
                        'deadline_date': hazard.deadline_date.strftime('%Y-%m-%d %H:%M:%S'),
                        'completion_date': hazard.completion_date.strftime('%Y-%m-%d %H:%M:%S') if hazard.completion_date else None,
                        'reviewer': hazard.reviewer,
                        'review_comment': hazard.review_comment,
                        'remarks': hazard.remarks,
                        'evaluation_id': hazard.evaluation_id,
                        'evaluation_info': hazard.get_evaluation_info(),
                        'is_overdue': hazard.is_overdue(),
                        'days_remaining': hazard.days_remaining(),
                        'attachments_count': len(hazard.get_attachments_info()),
                        'created_at': hazard.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                        'updated_at': hazard.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
                    }
                    hazards.append(hazard_data)
                except Exception as eval_error:
                    logger.warning(f"处理隐患记录 {hazard.task_id} 时出错: {eval_error}")
                    continue
            
            pagination_info = {
                'current_page': page,
                'total_pages': paginator.num_pages,
                'total_count': paginator.count,
                'page_size': page_size,
                'has_next': page_obj.has_next(),
                'has_previous': page_obj.has_previous(),
            }
            
            return create_success_response({
                'hazards': hazards,
                'pagination': pagination_info,
                'filters': {
                    'keyword': keyword,
                    'status': status,
                    'safety_level': safety_level,
                    'mine_name': mine_name,
                }
            })
            
        except Exception as e:
            logger.error(f"获取隐患追踪列表失败: {str(e)}", exc_info=True)
            return create_error_response('获取隐患追踪列表失败，请稍后重试', 500, 'LIST_FETCH_ERROR')
    
    elif request.method == 'POST':
        return create_hazard_tracking(request)


@csrf_exempt  
@require_http_methods(["POST"])
def create_hazard_tracking(request: HttpRequest) -> JsonResponse:
    """
    创建新的隐患追踪任务
    
    请求体应包含以下字段：
    - 必需字段：mine_name, indicator_name, safety_level, trigger_condition, remediation_suggestion
    - 可选字段：responsible_person, deadline_date, remarks, evaluation_id
    
    Returns:
        JsonResponse: 包含创建结果的JSON响应
    """
    try:
        # 解析请求数据
        try:
            data = json.loads(request.body.decode('utf-8'))
            logger.info(f"收到隐患追踪创建请求，数据: {data}")
        except (json.JSONDecodeError, UnicodeDecodeError) as e:
            logger.error(f"JSON解析错误: {e}")
            return create_error_response('请求数据格式错误', 400, 'INVALID_JSON')
        
        # 验证必需字段
        required_fields = ['mine_name', 'indicator_name', 'safety_level', 'trigger_condition', 'remediation_suggestion']
        missing_fields = [field for field in required_fields if not data.get(field)]
        if missing_fields:
            logger.warning(f"缺少必需字段: {missing_fields}")
            return create_error_response(f'缺少必需字段: {", ".join(missing_fields)}', 400, 'MISSING_REQUIRED_FIELDS')
        
        # 验证安全等级
        safety_level = data.get('safety_level')
        if safety_level not in VALID_LEVEL_CHOICES:
            return create_error_response(f'无效的安全等级，仅支持: {", ".join(VALID_LEVEL_CHOICES)}', 400, 'INVALID_SAFETY_LEVEL')
        
        # 处理截止日期
        deadline_date = data.get('deadline_date')
        if deadline_date:
            try:
                if isinstance(deadline_date, str):
                    deadline_date = datetime.strptime(deadline_date, '%Y-%m-%d %H:%M:%S')
            except ValueError:
                try:
                    deadline_date = datetime.strptime(deadline_date, '%Y-%m-%d')
                except ValueError:
                    return create_error_response('截止日期格式错误，应为 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS', 400, 'INVALID_DATE_FORMAT')
        else:
            # 默认7天后截止
            deadline_date = timezone.now() + timedelta(days=7)
        
        # 处理安全评价关联
        safety_evaluation = None
        if data.get('evaluation_id'):
            try:
                safety_evaluation = SafetyEvaluation.objects.get(evaluation_id=data['evaluation_id'])
            except SafetyEvaluation.DoesNotExist:
                return create_error_response('指定的安全评价记录不存在', 400, 'EVALUATION_NOT_FOUND')
        
        # 使用事务创建隐患追踪记录
        with transaction.atomic():
            hazard = HazardTracking(
                mine_name=data['mine_name'],
                indicator_name=data['indicator_name'],
                safety_level=safety_level,
                trigger_condition=data['trigger_condition'],
                remediation_suggestion=data['remediation_suggestion'],
                responsible_person=data.get('responsible_person', '待指派'),
                deadline_date=deadline_date,
                remarks=data.get('remarks', ''),
                safety_evaluation=safety_evaluation,
            )
            
            # 保存到数据库
            hazard.save()
            
            logger.info(f"成功创建隐患追踪任务: {hazard.task_id}")
            
            return create_success_response({
                'task_id': hazard.task_id,
                'mine_name': hazard.mine_name,
                'indicator_name': hazard.indicator_name,
                'status': hazard.status,
                'assigned_date': hazard.assigned_date.strftime('%Y-%m-%d %H:%M:%S'),
                'deadline_date': hazard.deadline_date.strftime('%Y-%m-%d %H:%M:%S'),
            }, '隐患追踪任务创建成功')
        
    except ValidationError as ve:
        logger.warning(f"隐患追踪数据验证失败: {ve}")
        return create_error_response(f'数据验证失败: {ve}', 400, 'VALIDATION_ERROR')
    except Exception as e:
        logger.error(f"创建隐患追踪任务失败: {str(e)}", exc_info=True)
        return create_error_response('创建隐患追踪任务失败，请稍后重试', 500, 'CREATE_ERROR')


@csrf_exempt
@require_http_methods(["GET", "PUT", "DELETE"])
def hazard_tracking_detail(request: HttpRequest, task_id: str) -> JsonResponse:
    """
    隐患追踪详情API
    
    GET: 获取隐患追踪详细信息
    PUT: 更新隐患追踪数据
    DELETE: 删除隐患追踪记录
    
    Args:
        task_id: 隐患追踪任务ID
    
    Returns:
        JsonResponse: 包含操作结果的JSON响应
    """
    try:
        hazard = get_object_or_404(HazardTracking, task_id=task_id)
    except Exception as e:
        logger.warning(f"隐患追踪记录不存在: task_id={task_id}")
        return create_error_response('隐患追踪记录不存在', 404, 'HAZARD_NOT_FOUND')
    
    if request.method == 'GET':
        try:
            # 构建详细信息响应
            hazard_data = {
                'task_id': hazard.task_id,
                'mine_name': hazard.mine_name,
                'indicator_name': hazard.indicator_name,
                'safety_level': hazard.safety_level,
                'trigger_condition': hazard.trigger_condition,
                'remediation_suggestion': hazard.remediation_suggestion,
                'responsible_person': hazard.responsible_person,
                'status': hazard.status,
                'assigned_date': hazard.assigned_date.strftime('%Y-%m-%d %H:%M:%S'),
                'deadline_date': hazard.deadline_date.strftime('%Y-%m-%d %H:%M:%S'),
                'completion_date': hazard.completion_date.strftime('%Y-%m-%d %H:%M:%S') if hazard.completion_date else None,
                'reviewer': hazard.reviewer,
                'review_comment': hazard.review_comment,
                'remarks': hazard.remarks,
                'evaluation_id': hazard.evaluation_id,
                'evaluation_info': hazard.get_evaluation_info(),
                'attachments': hazard.get_attachments_info(),
                'remediation_image': {
                    'has_image': bool(hazard.remediation_image),
                    'image_url': f"{request.scheme}://{request.get_host()}{settings.MEDIA_URL}{hazard.remediation_image.name}" if hazard.remediation_image else None,
                    'image_name': os.path.basename(hazard.remediation_image.name) if hazard.remediation_image else None,
                },
                'is_overdue': hazard.is_overdue(),
                'days_remaining': hazard.days_remaining(),
                'created_at': hazard.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'updated_at': hazard.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
            }
            
            return create_success_response(hazard_data)
            
        except Exception as e:
            logger.error(f"获取隐患追踪详情失败 (task_id: {task_id}): {str(e)}", exc_info=True)
            return create_error_response('获取隐患追踪详情失败', 500, 'DETAIL_FETCH_ERROR')
    
    elif request.method == 'PUT':
        try:
            # 解析请求数据
            try:
                data = json.loads(request.body.decode('utf-8'))
            except (json.JSONDecodeError, UnicodeDecodeError):
                return create_error_response('请求数据格式错误', 400, 'INVALID_JSON')
            
            # 使用事务更新记录
            with transaction.atomic():
                # 更新基本信息
                if 'mine_name' in data and data['mine_name'].strip():
                    hazard.mine_name = data['mine_name'].strip()
                
                if 'indicator_name' in data and data['indicator_name'].strip():
                    hazard.indicator_name = data['indicator_name'].strip()
                
                if 'safety_level' in data and data['safety_level'] in VALID_LEVEL_CHOICES:
                    hazard.safety_level = data['safety_level']
                
                if 'trigger_condition' in data:
                    hazard.trigger_condition = data['trigger_condition']
                
                if 'remediation_suggestion' in data:
                    hazard.remediation_suggestion = data['remediation_suggestion']
                
                if 'responsible_person' in data:
                    hazard.responsible_person = data['responsible_person']
                
                if 'status' in data and data['status'] in VALID_STATUS_CHOICES:
                    hazard.status = data['status']
                
                if 'reviewer' in data:
                    hazard.reviewer = data['reviewer']
                
                if 'review_comment' in data:
                    hazard.review_comment = data['review_comment']
                
                if 'remarks' in data:
                    hazard.remarks = data['remarks']
                
                # 处理截止日期
                if 'deadline_date' in data and data['deadline_date']:
                    try:
                        if isinstance(data['deadline_date'], str):
                            hazard.deadline_date = datetime.strptime(data['deadline_date'], '%Y-%m-%d %H:%M:%S')
                    except ValueError:
                        try:
                            hazard.deadline_date = datetime.strptime(data['deadline_date'], '%Y-%m-%d')
                        except ValueError:
                            return create_error_response('截止日期格式错误，应为 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS', 400)
                
                # 验证并保存
                hazard.full_clean()
                hazard.save()
                
                logger.info(f"成功更新隐患追踪任务: {hazard.task_id}")
                
                return create_success_response({
                    'task_id': hazard.task_id,
                    'status': hazard.status,
                    'updated_at': hazard.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
                }, '隐患追踪任务更新成功')
            
        except ValidationError as ve:
            logger.warning(f"更新隐患追踪数据验证失败 (task_id: {task_id}): {ve}")
            return create_error_response(f'数据验证失败: {ve}', 400, 'VALIDATION_ERROR')
        except Exception as e:
            logger.error(f"更新隐患追踪任务失败 (task_id: {task_id}): {str(e)}", exc_info=True)
            return create_error_response('更新隐患追踪任务失败，请稍后重试', 500, 'UPDATE_ERROR')
    
    elif request.method == 'DELETE':
        try:
            with transaction.atomic():
                task_id_str = hazard.task_id
                hazard.delete()
                
                logger.info(f"成功删除隐患追踪任务: {task_id_str}")
                
                return create_success_response(message='隐患追踪任务删除成功')
            
        except Exception as e:
            logger.error(f"删除隐患追踪任务失败 (task_id: {task_id}): {str(e)}", exc_info=True)
            return create_error_response('删除隐患追踪任务失败，请稍后重试', 500, 'DELETE_ERROR')


@csrf_exempt
@require_http_methods(["POST"])
def create_hazards_from_evaluation(request: HttpRequest) -> JsonResponse:
    """
    从安全评价报告创建隐患追踪任务
    
    用于将安全评价中发现的C级和D级问题自动转换为隐患追踪任务
    
    请求体应包含：
    - evaluation_id: 评价记录ID
    - mine_name: 矿山名称
    - remediation_suggestions: 整改建议列表
    
    Returns:
        JsonResponse: 包含创建结果的JSON响应
    """
    try:
        # 解析请求数据
        try:
            data = json.loads(request.body.decode('utf-8'))
            logger.info(f"收到从评价报告创建隐患任务请求，数据: {data}")
        except (json.JSONDecodeError, UnicodeDecodeError) as e:
            logger.error(f"JSON解析错误: {e}")
            return create_error_response('请求数据格式错误', 400, 'INVALID_JSON')
        
        # 验证必需字段
        required_fields = ['evaluation_id', 'mine_name', 'remediation_suggestions']
        missing_fields = [field for field in required_fields if not data.get(field)]
        if missing_fields:
            return create_error_response(f'缺少必需字段: {", ".join(missing_fields)}', 400, 'MISSING_REQUIRED_FIELDS')
        
        evaluation_id = data['evaluation_id']
        mine_name = data['mine_name']
        remediation_suggestions = data['remediation_suggestions']
        
        if not isinstance(remediation_suggestions, list):
            return create_error_response('整改建议必须是列表格式', 400, 'INVALID_SUGGESTIONS_FORMAT')
        
        # 获取安全评价对象
        try:
            safety_evaluation = SafetyEvaluation.objects.get(evaluation_id=evaluation_id)
        except SafetyEvaluation.DoesNotExist:
            return create_error_response('指定的安全评价记录不存在', 400, 'EVALUATION_NOT_FOUND')
        
        # 使用事务批量创建隐患追踪任务
        with transaction.atomic():
            created_tasks = []
            
            for suggestion in remediation_suggestions:
                try:
                    # 根据安全等级确定等级
                    safety_level = 'D级(较差)' if suggestion.get('安全等级') == '危险' else 'C级(一般)'
                    
                    hazard = HazardTracking.objects.create(
                        mine_name=mine_name,
                        indicator_name=suggestion.get('指标名称', ''),
                        safety_level=safety_level,
                        trigger_condition=suggestion.get('触发条件', ''),
                        remediation_suggestion=suggestion.get('建议内容', ''),
                        responsible_person='待指派',
                        deadline_date=timezone.now() + timedelta(days=7),
                        safety_evaluation=safety_evaluation,
                        remarks=f'由安全评价报告自动生成（评价编号: {evaluation_id}）'
                    )
                    
                    created_tasks.append({
                        'task_id': hazard.task_id,
                        'indicator_name': hazard.indicator_name,
                        'safety_level': hazard.safety_level,
                    })
                    
                except Exception as task_error:
                    logger.warning(f"创建隐患任务失败: {task_error}")
                    continue
            
            logger.info(f"成功从评价报告创建 {len(created_tasks)} 个隐患追踪任务")
            
            return create_success_response({
                'created_count': len(created_tasks),
                'tasks': created_tasks,
                'evaluation_id': evaluation_id,
            }, f'成功创建 {len(created_tasks)} 个隐患追踪任务')
        
    except Exception as e:
        logger.error(f"从评价报告创建隐患任务失败: {str(e)}", exc_info=True)
        return create_error_response('从评价报告创建隐患任务失败，请稍后重试', 500, 'CREATE_FROM_EVALUATION_ERROR')


@require_http_methods(["GET"])
def get_hazard_statistics(request: HttpRequest) -> JsonResponse:
    """
    获取隐患追踪统计数据
    
    提供系统中隐患追踪数据的综合统计信息
    
    Returns:
        JsonResponse: 包含统计数据的JSON响应
    """
    try:
        statistics = HazardTracking.get_statistics()
        
        # 添加更多统计信息
        statistics.update({
            'completion_rate': round(
                (statistics['completed_count'] + statistics['verified_count']) / statistics['total_count'] * 100, 2
            ) if statistics['total_count'] > 0 else 0,
            'overdue_rate': round(
                statistics['overdue_count'] / statistics['total_count'] * 100, 2
            ) if statistics['total_count'] > 0 else 0,
        })
        
        # 按矿山统计
        mine_stats = []
        mines = HazardTracking.objects.values('mine_name').distinct()
        for mine in mines:
            mine_name = mine['mine_name']
            mine_count = HazardTracking.objects.filter(mine_name=mine_name).count()
            mine_pending = HazardTracking.objects.filter(mine_name=mine_name, status='待整改').count()
            mine_stats.append({
                'mine_name': mine_name,
                'total_count': mine_count,
                'pending_count': mine_pending,
            })
        
        statistics['mine_statistics'] = mine_stats
        statistics['calculation_timestamp'] = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
        
        logger.info(f"成功生成隐患追踪统计数据: 总计 {statistics['total_count']} 条记录")
        
        return create_success_response(statistics, '统计数据获取成功')
        
    except Exception as e:
        logger.error(f"获取隐患追踪统计数据失败: {str(e)}", exc_info=True)
        return create_error_response('获取统计数据失败，请稍后重试', 500, 'STATISTICS_ERROR')


@csrf_exempt
@require_http_methods(["POST"])
def upload_hazard_attachment(request: HttpRequest, task_id: str) -> JsonResponse:
    """
    上传隐患追踪附件
    
    Args:
        task_id: 隐患追踪任务ID
    
    Returns:
        JsonResponse: 包含上传结果的JSON响应
    """
    try:
        hazard = get_object_or_404(HazardTracking, task_id=task_id)
    except Exception as e:
        return create_error_response('隐患追踪记录不存在', 404, 'HAZARD_NOT_FOUND')
    
    try:
        # 获取上传的文件
        uploaded_file = request.FILES.get('file')
        description = request.POST.get('description', '')
        
        if not uploaded_file:
            return create_error_response('请选择要上传的文件', 400, 'NO_FILE_PROVIDED')
        
        # 创建上传目录
        upload_dir = os.path.join(settings.MEDIA_ROOT, 'hazard_attachments', task_id)
        os.makedirs(upload_dir, exist_ok=True)
        
        # 生成文件名
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        file_name = f"{timestamp}_{uploaded_file.name}"
        file_path = os.path.join(upload_dir, file_name)
        
        # 保存文件
        with open(file_path, 'wb+') as destination:
            for chunk in uploaded_file.chunks():
                destination.write(chunk)
        
        # 添加附件信息到隐患记录
        file_info = {
            'file_name': uploaded_file.name,
            'file_path': os.path.join('hazard_attachments', task_id, file_name),
            'file_size': uploaded_file.size,
            'description': description,
        }
        
        hazard.add_attachment(file_info)
        
        logger.info(f"成功上传隐患追踪附件: {task_id} - {uploaded_file.name}")
        
        return create_success_response({
            'task_id': task_id,
            'file_name': uploaded_file.name,
            'file_size': uploaded_file.size,
            'description': description,
        }, '附件上传成功')
        
    except Exception as e:
        logger.error(f"上传隐患追踪附件失败 (task_id: {task_id}): {str(e)}", exc_info=True)
        return create_error_response('上传附件失败，请稍后重试', 500, 'UPLOAD_ERROR')


@csrf_exempt
@require_http_methods(["POST"])
def upload_remediation_image(request: HttpRequest, task_id: str) -> JsonResponse:
    """
    上传隐患整改图片
    
    每个隐患只能上传一张整改图片，如果已存在则覆盖
    
    Args:
        task_id: 隐患追踪任务ID
    
    Returns:
        JsonResponse: 包含上传结果的JSON响应
    """
    try:
        hazard = get_object_or_404(HazardTracking, task_id=task_id)
    except Exception as e:
        return create_error_response('隐患追踪记录不存在', 404, 'HAZARD_NOT_FOUND')
    
    try:
        # 获取上传的图片文件
        uploaded_image = request.FILES.get('image')
        
        if not uploaded_image:
            return create_error_response('请选择要上传的图片', 400, 'NO_IMAGE_PROVIDED')
        
        # 验证文件类型
        allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']
        if uploaded_image.content_type not in allowed_types:
            return create_error_response('只支持 JPG、PNG、GIF、WebP 格式的图片', 400, 'INVALID_IMAGE_TYPE')
        
        # 验证文件大小（限制为10MB）
        max_size = 10 * 1024 * 1024  # 10MB
        if uploaded_image.size > max_size:
            return create_error_response('图片大小不能超过10MB', 400, 'IMAGE_TOO_LARGE')
        
        # 删除旧的整改图片（如果存在）
        if hazard.remediation_image:
            try:
                old_image_path = hazard.remediation_image.path
                if os.path.exists(old_image_path):
                    os.remove(old_image_path)
            except Exception as e:
                logger.warning(f"删除旧整改图片失败: {e}")
        
        # 保存新的整改图片
        hazard.remediation_image = uploaded_image
        hazard.save()
        
        logger.info(f"成功上传隐患整改图片: {task_id} - {uploaded_image.name}")
        
        return create_success_response({
            'task_id': task_id,
            'image_url': f"{request.scheme}://{request.get_host()}{settings.MEDIA_URL}{hazard.remediation_image.name}" if hazard.remediation_image else None,
            'image_name': uploaded_image.name,
            'image_size': uploaded_image.size,
        }, '整改图片上传成功')
        
    except Exception as e:
        logger.error(f"上传隐患整改图片失败 (task_id: {task_id}): {str(e)}", exc_info=True)
        return create_error_response('上传整改图片失败，请稍后重试', 500, 'IMAGE_UPLOAD_ERROR')


@require_http_methods(["GET"])
def get_remediation_image(request: HttpRequest, task_id: str) -> JsonResponse:
    """
    获取隐患整改图片信息
    
    Args:
        task_id: 隐患追踪任务ID
    
    Returns:
        JsonResponse: 包含图片信息的JSON响应
    """
    try:
        hazard = get_object_or_404(HazardTracking, task_id=task_id)
    except Exception as e:
        return create_error_response('隐患追踪记录不存在', 404, 'HAZARD_NOT_FOUND')
    
    try:
        if not hazard.remediation_image:
            return create_success_response({
                'task_id': task_id,
                'has_image': False,
                'image_url': None,
                'image_name': None,
                'upload_time': None,
            })
        
        # 获取图片信息
        image_info = {
            'task_id': task_id,
            'has_image': True,
            'image_url': f"{request.scheme}://{request.get_host()}{settings.MEDIA_URL}{hazard.remediation_image.name}",
            'image_name': os.path.basename(hazard.remediation_image.name),
            'upload_time': hazard.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
        }
        
        return create_success_response(image_info)
        
    except Exception as e:
        logger.error(f"获取隐患整改图片失败 (task_id: {task_id}): {str(e)}", exc_info=True)
        return create_error_response('获取整改图片失败，请稍后重试', 500, 'IMAGE_FETCH_ERROR')


@csrf_exempt
@require_http_methods(["DELETE"])
def delete_remediation_image(request: HttpRequest, task_id: str) -> JsonResponse:
    """
    删除隐患整改图片
    
    Args:
        task_id: 隐患追踪任务ID
    
    Returns:
        JsonResponse: 包含删除结果的JSON响应
    """
    try:
        hazard = get_object_or_404(HazardTracking, task_id=task_id)
    except Exception as e:
        return create_error_response('隐患追踪记录不存在', 404, 'HAZARD_NOT_FOUND')
    
    try:
        if not hazard.remediation_image:
            return create_error_response('该隐患没有整改图片', 400, 'NO_IMAGE_TO_DELETE')
        
        # 删除文件系统中的图片文件
        try:
            image_path = hazard.remediation_image.path
            if os.path.exists(image_path):
                os.remove(image_path)
        except Exception as e:
            logger.warning(f"删除图片文件失败: {e}")
        
        # 清空数据库中的图片字段
        hazard.remediation_image = None
        hazard.save()
        
        logger.info(f"成功删除隐患整改图片: {task_id}")
        
        return create_success_response({
            'task_id': task_id,
        }, '整改图片删除成功')
        
    except Exception as e:
        logger.error(f"删除隐患整改图片失败 (task_id: {task_id}): {str(e)}", exc_info=True)
        return create_error_response('删除整改图片失败，请稍后重试', 500, 'IMAGE_DELETE_ERROR')

